﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using DocumentFormat.OpenXml.Packaging;
using OpenXmlPowerTools;
using System.IO;
using System.Drawing;

namespace Songhay.OpenXml
{
    using Songhay.OpenXml.Models;

    /// <summary>
    /// Static members for Open XML.
    /// </summary>
    public static partial class OpenXmlUtility
    {
        /// <summary>
        /// Processes the image.
        /// </summary>
        /// <param name="wordDoc">The word doc.</param>
        /// <param name="element">The element.</param>
        /// <param name="imageHandler">The image handler.</param>
        /// <remarks>
        /// </remarks>
        public static XElement ProcessImage(WordprocessingDocument wordDoc,
            XElement element, Func<ImageInfo, XElement> imageHandler)
        {
            if(element.Name == W.drawing)
            {
                XElement containerElement = element.Elements()
                    .Where(e => e.Name == WP.inline || e.Name == WP.anchor)
                    .FirstOrDefault();
                if(containerElement != null)
                {
                    int? extentCx = (int?)containerElement.Elements(WP.extent)
                        .Attributes(WPNoNamespace.cx).FirstOrDefault();
                    int? extentCy = (int?)containerElement.Elements(WP.extent)
                        .Attributes(WPNoNamespace.cy).FirstOrDefault();
                    string altText = (string)containerElement.Elements(WP.docPr)
                        .Attributes(WPNoNamespace.descr).FirstOrDefault();
                    if(altText == null)
                        altText = (string)containerElement.Elements(WP.docPr)
                            .Attributes(WPNoNamespace.name).FirstOrDefault();
                    if(altText == null)
                        altText = "";

                    XElement blipFill = containerElement.Elements(A.graphic)
                        .Elements(A.graphicData)
                        .Elements(Pic.pic).Elements(Pic.blipFill).FirstOrDefault();
                    if(blipFill != null)
                    {
                        string imageRid = (string)blipFill.Elements(A.blip).Attributes(R.embed)
                            .FirstOrDefault();
                        ImagePart imagePart = (ImagePart)wordDoc.MainDocumentPart
                            .GetPartById(imageRid);
                        string contentType = imagePart.ContentType;
                        if(contentType == "image/png" ||
                            contentType == "image/gif" ||
                            contentType == "image/tiff" ||
                            contentType == "image/jpeg")
                        {
                            using(Stream partStream = imagePart.GetStream())
                            using(Bitmap bitmap = new Bitmap(partStream))
                            {
                                if(extentCx != null && extentCy != null)
                                {
                                    ImageInfo imageInfo = new ImageInfo()
                                    {
                                        Bitmap = bitmap,
                                        ImgStyleAttribute = new XAttribute(SonghayXhtml.style_attr,
                                            string.Format("width: {0}in; height: {1}in",
                                                (float)extentCx / (float)ImageInfo.EmusPerInch,
                                                (float)extentCy / (float)ImageInfo.EmusPerInch)),
                                        ContentType = contentType,
                                        DrawingElement = element,
                                        AltText = altText,
                                    };
                                    return imageHandler(imageInfo);
                                }
                                ImageInfo imageInfo2 = new ImageInfo()
                                {
                                    Bitmap = bitmap,
                                    ContentType = contentType,
                                    DrawingElement = element,
                                    AltText = altText,
                                };
                                return imageHandler(imageInfo2);
                            };
                        }
                    }
                }
            }
            if(element.Name == W.pict)
            {
                string imageRid = (string)element.Elements(VML.shape)
                    .Elements(VML.imagedata).Attributes(R.id).FirstOrDefault();
                string style = (string)element.Elements(VML.shape)
                    .Attributes(SonghayXhtml.style_attr).FirstOrDefault();
                if(imageRid != null)
                {
                    try
                    {
                        ImagePart imagePart = (ImagePart)wordDoc.MainDocumentPart
                            .GetPartById(imageRid);
                        string contentType = imagePart.ContentType;
                        if(contentType == "image/png" ||
                            contentType == "image/gif" ||
                            contentType == "image/tiff" ||
                            contentType == "image/jpeg")
                        {
                            //string style = element.
                            using(Stream partStream = imagePart.GetStream())
                            using(Bitmap bitmap = new Bitmap(partStream))
                            {
                                ImageInfo imageInfo = new ImageInfo()
                                {
                                    Bitmap = bitmap,
                                    ContentType = contentType,
                                    DrawingElement = element,
                                };
                                if(style != null)
                                {
                                    float? widthInPoints = null;
                                    float? heightInPoints = null;
                                    string[] tokens = style.Split(';');
                                    var widthString = tokens
                                        .Select(t => new
                                        {
                                            Name = t.Split(':').First(),
                                            Value = t.Split(':').Skip(1)
                                                .Take(1).FirstOrDefault(),
                                        })
                                        .Where(p => p.Name == "width")
                                        .Select(p => p.Value)
                                        .FirstOrDefault();
                                    if(widthString != null &&
                                        widthString.Substring(widthString.Length - 2) == "pt")
                                    {
                                        float w;
                                        if(float.TryParse(widthString.Substring(0,
                                            widthString.Length - 2), out w))
                                            widthInPoints = w;
                                    }
                                    var heightString = tokens
                                        .Select(t => new
                                        {
                                            Name = t.Split(':').First(),
                                            Value = t.Split(':').Skip(1).Take(1).FirstOrDefault(),
                                        })
                                        .Where(p => p.Name == "height")
                                        .Select(p => p.Value)
                                        .FirstOrDefault();
                                    if(heightString != null &&
                                        heightString.Substring(heightString.Length - 2) == "pt")
                                    {
                                        float h;
                                        if(float.TryParse(heightString.Substring(0,
                                            heightString.Length - 2), out h))
                                            heightInPoints = h;
                                    }
                                    if(widthInPoints != null && heightInPoints != null)
                                        imageInfo.ImgStyleAttribute = new XAttribute(
                                            SonghayXhtml.style_attr, string.Format(
                                                "width: {0}pt; height: {1}pt",
                                                widthInPoints, heightInPoints));
                                }
                                return imageHandler(imageInfo);
                            };
                        }
                    }
                    catch(ArgumentOutOfRangeException)
                    {
                        return null;
                    }
                }
            }
            return null;
        }
    }
}
